

<!DOCTYPE html>
<html lang="en" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/avatar.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Hughie">
  <meta name="keywords" content="">
  
    <meta name="description" content="StringBuffer与StringBuilder通常说单线程情况下StringBuilder性能优于StringBuffer，但StringBuilder是线程不安全的，所以多线程并发编程时候要用StringBuffer。那么，StringBuffer是如何保证线程安全的呢？ 来看看源码 StringBuilder  StringBuffer  从源码中可以看出StringBuffer和Str">
<meta property="og:type" content="article">
<meta property="og:title" content="StringBuffer线程安全的实现">
<meta property="og:url" content="https://hughie-hy.gitee.io/2022/03/03/StringBuffer%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%AE%9E%E7%8E%B0/index.html">
<meta property="og:site_name" content="Hughie&#39;s blog">
<meta property="og:description" content="StringBuffer与StringBuilder通常说单线程情况下StringBuilder性能优于StringBuffer，但StringBuilder是线程不安全的，所以多线程并发编程时候要用StringBuffer。那么，StringBuffer是如何保证线程安全的呢？ 来看看源码 StringBuilder  StringBuffer  从源码中可以看出StringBuffer和Str">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://hughie-hy.gitee.io/img/java.png">
<meta property="article:published_time" content="2022-03-02T16:00:00.000Z">
<meta property="article:modified_time" content="2022-03-04T06:21:22.794Z">
<meta property="article:author" content="Hughie">
<meta property="article:tag" content="Java基础">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://hughie-hy.gitee.io/img/java.png">
  
  
  <title>StringBuffer线程安全的实现 - Hughie&#39;s blog</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hint.css@2/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"hughie-hy.gitee.io","root":"/","version":"1.8.14","typing":{"enable":true,"typeSpeed":120,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.1"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Hughie</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                Home
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                Archives
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                Categories
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                Tags
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                About
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="StringBuffer线程安全的实现">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2022-03-03 00:00" pubdate>
        March 3, 2022 am
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      2.7k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      23 分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">StringBuffer线程安全的实现</h1>
            
            <div class="markdown-body">
              <h2 id="StringBuffer与StringBuilder"><a href="#StringBuffer与StringBuilder" class="headerlink" title="StringBuffer与StringBuilder"></a>StringBuffer与StringBuilder</h2><p>通常说单线程情况下StringBuilder性能优于StringBuffer，但StringBuilder是线程不安全的，所以多线程并发编程时候要用StringBuffer。那么，StringBuffer是如何保证线程安全的呢？</p>
<p>来看看源码</p>
<p>StringBuilder</p>
<p><img src="https://blog-chy.oss-cn-shenzhen.aliyuncs.com/static/image-20220304124024252.png" srcset="/img/loading.gif" lazyload></p>
<p>StringBuffer</p>
<p><img src="https://blog-chy.oss-cn-shenzhen.aliyuncs.com/static/image-20220304124839438.png" srcset="/img/loading.gif" lazyload></p>
<p>从源码中可以看出StringBuffer和StringBuilder来源出处是一致的，继承相同的类，实现相同的接口，继续往后看可以看到构造方法也是相同的。这里可以看出StringBuffer从JDK1.0开始就有，StringBuilder从JDK1.5才出现。</p>
<p>StringBuilder没有重写length()和capacity()等方法，StringBuffer给方法添加了同步锁，从这里开始，StringBuffer和StringBuilder出现区别。StringBuffer把所有操作类的方法均添加同步锁，而StringBuilder并没有。</p>
<p>StringBuffer的append方法：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> StringBuffer <span class="hljs-title function_">append</span><span class="hljs-params">(Object obj)</span> &#123;<br>    <span class="hljs-built_in">super</span>.append(String.valueOf(obj));<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> StringBuffer <span class="hljs-title function_">append</span><span class="hljs-params">(String str)</span> &#123;<br>    <span class="hljs-built_in">super</span>.append(str);<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>StringBuilder的append方法：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> StringBuffer <span class="hljs-title function_">append</span><span class="hljs-params">(Object obj)</span> &#123;<br>    toStringCache = <span class="hljs-literal">null</span>;<br>    <span class="hljs-built_in">super</span>.append(String.valueOf(obj));<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> StringBuffer <span class="hljs-title function_">append</span><span class="hljs-params">(String str)</span> &#123;<br>    toStringCache = <span class="hljs-literal">null</span>;<br>    <span class="hljs-built_in">super</span>.append(str);<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>这里append，作为StringBuffer&#x2F;StringBuilder最常用的方法之一，区别已经很明显了。</p>
<p>关于synchronized的描述：synchronized 方法控制对类成员变量的访问：每个类实例对应一把锁，每个 synchronized 方法都必须 获得调用该方法的类实例的锁方能执行，否则所属线程阻塞，方法一旦执行，就独占该锁，直到从该方法 返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行状态。</p>
<p>源码注释中这样写到：A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.（可变的字符序列。此类提供与 StringBuffer 兼容的 API，但不保证同步。此类设计用于在单个线程正在使用字符串缓冲区的地方（通常情况下）用作 StringBuffer 的替代品。在可能的情况下，建议优先使用此类而不是 StringBuffer，因为它在大多数实现下会更快。）</p>
<p>Hashtable和HashMap之间的关系也是类似的。Hashtable源码里，也充斥着synchronized。</p>
<h2 id="StringBuffer没有加synchronized关键字的方法是如何实现线程安全的"><a href="#StringBuffer没有加synchronized关键字的方法是如何实现线程安全的" class="headerlink" title="StringBuffer没有加synchronized关键字的方法是如何实现线程安全的"></a>StringBuffer没有加synchronized关键字的方法是如何实现线程安全的</h2><p>阅读源码的过程中发现StringBuffer中有的方法没有加了synchronized关键字有的没有，比如StringBuffer insert(int offset, int i)，那没有加synchronized关键字的方法是如何实现线程安全的呢，找到该方法的源码：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> StringBuffer <span class="hljs-title function_">insert</span><span class="hljs-params">(<span class="hljs-type">int</span> offset, <span class="hljs-type">int</span> i)</span> &#123;<br>    <span class="hljs-comment">// Note, synchronization achieved via invocation of StringBuffer insert(int, String)</span><br>    <span class="hljs-comment">// after conversion of i to String by super class method</span><br>    <span class="hljs-comment">// Ditto for toStringCache clearing</span><br>    <span class="hljs-built_in">super</span>.insert(offset, i);<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>注释意思为该方法是通过调用<code>StringBuffer insert(int, String)</code>这一重载方法进行实现的，父类会将i转换为String类型。查看父类AbstractStringBuilder的源码</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> AbstractStringBuilder <span class="hljs-title function_">insert</span><span class="hljs-params">(<span class="hljs-type">int</span> offset, <span class="hljs-type">int</span> i)</span> &#123;<br>    <span class="hljs-keyword">return</span> insert(offset, String.valueOf(i));<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>可以看到这里又调用了一个insert方法，此时会再次调用<code>StringBuffer的insert(int, String)</code>方法，该方法是由synchronized修饰的</p>
<p><code>StringBuffer insert(int, String)</code>源码：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-comment">//同步方法</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> StringBuffer <span class="hljs-title function_">insert</span><span class="hljs-params">(<span class="hljs-type">int</span> offset, String str)</span> &#123;<br>    toStringCache = <span class="hljs-literal">null</span>;<br>    <span class="hljs-built_in">super</span>.insert(offset, str);<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;<br>&#125;<br></code></pre></div></td></tr></table></figure>



<h2 id="知识点复习：重载与重写"><a href="#知识点复习：重载与重写" class="headerlink" title="知识点复习：重载与重写"></a>知识点复习：重载与重写</h2><p><img src="https://blog-chy.oss-cn-shenzhen.aliyuncs.com/static/image-20220304121907759.png" srcset="/img/loading.gif" lazyload></p>
<h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><section class="footnotes"><div class="footnote-list"><ol><li><span id="fn:1" class="footnote-text"><span><a target="_blank" rel="noopener" href="https://blog.csdn.net/lies_joker/article/details/45217413">https://blog.csdn.net/lies_joker/article/details/45217413</a>
<a href="#fnref:1" rev="footnote" class="footnote-backref"> ↩</a></span></span></li><li><span id="fn:2" class="footnote-text"><span><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/505792481">https://www.zhihu.com/question/505792481</a>
<a href="#fnref:2" rev="footnote" class="footnote-backref"> ↩</a></span></span></li></ol></div></section>
            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Java/">Java</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Java%E5%9F%BA%E7%A1%80/">Java基础</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/03/05/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%AC%94%E8%AE%B0%EF%BC%88%E4%B8%80%EF%BC%89%E5%9F%BA%E7%A1%80/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">并发编程笔记（一）基础</span>
                        <span class="visible-mobile">Previous</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/02/27/Java%E5%BC%82%E5%B8%B8/">
                        <span class="hidden-mobile">Java异常</span>
                        <span class="visible-mobile">Next</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;TOC</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">Search</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">keyword</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
        typing(title);
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
